package com.chentf.algorithm.algorithm.StringAndArrays;

/**
 * 最长公共前缀:
 * 编写一个函数来查找字符串数组中的最长公共前缀。
 * 如果不存在公共前缀，返回空字符串 ""。
 * 示例 1：
 * 输入：strs = ["flower","flow","flight"]
 * 输出："fl"
 * 示例 2：
 * 输入：strs = ["dog","racecar","car"]
 * 输出：""
 * 解释：输入不存在公共前缀。
 */
public class LongestCommonPrefix {

    public static void main(String[] args) {
        String[] strs = {"flower","flow","flight"};
        System.out.println(longestCommonPrefix01(strs));
        System.out.println(longestCommonPrefix02(strs));
    }

    /**
     * 依次遍历字符串数组中的每个字符串，对于每个遍历到的字符串，更新最长公共前缀，当遍历完所有的字符串以后，即可得到字符串数组中的最长公共前缀。
     * 如果在尚未遍历完所有的字符串时，最长公共前缀已经是空串，则最长公共前缀一定是空串，因此不需要继续遍历剩下的字符串，直接返回空串即可。
     */
    // 方式一：横向比较
    public static String longestCommonPrefix01(String[] strs) {
        if(strs == null || strs.length == 0){
            return null;
        }
        // 最长公共前缀，获取第一个字符串作为最长公共前缀
        String prefix = strs[0];
        int count = strs.length;
        for (int i = 1; i < count; i++) {
            // 前后比较，横向比较
            prefix = longestCommonPrefix(prefix, strs[i]);
            if(prefix.length() == 0){
                // 最长公共前缀已经是空串，则最长公共前缀一定是空串，因此不需要继续遍历剩下的字符串，直接返回空串即可。
                break;
            }
        }
        return prefix;
    }

    private static String longestCommonPrefix(String str1, String str2) {
        // 取两个字符串的长度较小的一个作为循环的上限
        int length = Math.min(str1.length(), str2.length());
        int index = 0;
        while(index < length && str1.charAt(index) == str2.charAt(index)){
            // 循环比较，直到找到第一个不相等的字符
            index++;
        }
        return str1.substring(0, index);
    }

    /**
     * 纵向扫描时，从前往后遍历所有字符串的每一列，
     * 比较相同列上的字符是否相同，如果相同则继续对下一列进行比较，
     * 如果不相同则当前列不再属于公共前缀，当前列之前的部分为最长公共前缀。
     */
    // 方式二：纵向比较

    public static String longestCommonPrefix02(String[] strs){
        if(strs == null || strs.length == 0){
            return null;
        }
        // 最长公共前缀，获取第一个字符串作为最长公共前缀
        int length = strs[0].length();
        int count = strs.length;
        for (int i = 0; i < count; i++) {
            // 前后比较，纵向比较
            char c = strs[0].charAt(i);
            for (int j = 1; j < count; j++) {
                // 如果当前列不再属于公共前缀，当前列之前的部分为最长公共前缀。
                if(i == strs[j].length() || strs[j].charAt(i)!= c){
                    // 最长公共前缀已经是空串，则最长公共前缀一定是空串，因此不需要继续遍历剩下的字符串，直接返回空串即可。
                    return strs[0].substring(0, i);
                }
            }
        }
        return strs[0];
    }
}
